RecyclerView 運用來 View 展示 像是 ArrayList 或是 MutableList 這種集合
將多筆數據視覺化 , 可以讓我們很清楚所有數據 , 像是 Line 的聊天訊息 , 抑或是收藏
清單 , 都可以運用 RecyclerView 來完成。
RecyclerView 最好不要自定義高度 , 最好能 match_parent 或 wrap_content
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
記得 ViewGroup 高度(下面是 constraintlayout) 一定要 wrap_content 哦
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF">
<TextView
android:id="@+id/num_text"
android:layout_width="130dp"
android:layout_height="85dp"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:layout_marginStart="116dp"
android:layout_marginLeft="116dp"
android:gravity="center|center_vertical"
android:text="1"
android:textColor="@android:color/black"
android:textSize="30sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
定義要展示的數據 , 前面有提到RecyclerView 是用來展示多筆數據的 , 既然如此,一定要有數據讓他呈現
如果沒有數據 RecyclerView 會是空白的狀態。
建立Adapter ,Adapter 負責 管理所有 Recyclerview 的 View ,
將所有數據加入集合
Adapter 內會定義一個變數 , 在 update 方法中 我們會讓裡面定義好的變數指向外面的集合物件(數據),在執行 notifyDataSetChanged() , 通知畫面做變更 。 如果沒通知畫面做變更 , 並重新繪製我們 RecyclerView , 就算數據是非空的狀態 , 畫面上仍然會保持空白的狀態 。
將我們設定好的 Adapter 傳遞給 RecyclerView adapter 變數, 並將 LinearLayoutManager (要傳入 Context) , 傳遞給 RecyclerView layoutManager
class MainActivity : AppCompatActivity() {
// 1 )
val list = mutableListOf<Int>()
// 2 )
val this_adapter = Adapter(this)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setList()
initRecyclerView()
}
fun setList() {
// 3 )
for(i in 0 .. 75){
list.add(i)
}
// 4 )
this_adapter.update(list)
}
// 5)
fun initRecyclerView(){
recyclerview.apply{
adapter = this_adapter
layoutManager = LinearLayoutManager(this@MainActivity)
}
}
}
Adapter 傳遞 Context 給他 , Context 在 onCreateViewHolder 會用到
在這裡處理 Adapter 數據的做法是 ,在裡面也定義集合(innerList), 這個 Adapter 是依據 innerList的數據做畫面上的呈現 , 但只要 innerList 數據一做變動 , 必須提醒畫面數據變動了應該重畫了。
在 onCreateViewHolder 創建我們所需的 ViewHolder 物件 , 例如 RecyclerView一次可以顯示5個項目,它將創建5-6個 ViewHolder,每次調用onBindViewHolder 時 , 自動復用這些 ViewHolder 物件。
getItemCount 在這裡我們可以很清楚的知道 , RecyclerView 的view呈現是依據 innerList 的數據
onBindViewHolder 在這裏需要依據 數據 強制綁定 viewHolder 中的 view , 因為 Recyclerview 具有復用的View 的機制 , 如果沒有依據數據去強制綁定 view , 你只要改動一個 view , 例如 checkbox 的點選 , 你會發現往下滑時 , 接下來好幾個 view 都會是 被打勾的狀態
ViewHolder 顧名思義 , 是裝 View 的容器 , 在 調用 OnBindViewHolder 時 , 將數據 與 這個位置的 viewHolder 所裝的 View 繫結在一起 。
自定義 update 方法 , 在前面有小小提到 , 目的是當數據做變動時 , 讓 innerList 指向新數據物件 , 在這裏是一個 mutablelist , 讓 innerList 指向新數據 的 mutablelist , 當 innerList 變動時要記得調用 notifyDataSetChanged() 提醒 View 數據改變了, 需要重畫
class Adapter(var ct:Context) :RecyclerView.Adapter<Adapter.ViewHolder>() {
var innerList = mutableListOf<Int>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Adapter.ViewHolder {
val view = LayoutInflater.from(ct).inflate(R.layout.itemview,parent,false)
return ViewHolder(view)
}
override fun getItemCount(): Int = innerList.size
override fun onBindViewHolder(holder: Adapter.ViewHolder, position: Int) {
holder.setUI(innerList[position])
}
inner class ViewHolder(view: View):RecyclerView.ViewHolder(view){
val num_text = view.num_text
fun setUI(number:Int){
num_text.text = number.toString()
}
}
fun update(list:MutableList<Int>){
innerList = list
notifyDataSetChanged()
}
}